/*
 * =====================================================================================
 *       Filename:  simq.c
 *    Description:  简单队列服务主程序
 *        Version:  1.1.0
 *        Created:  2015-01-07 15:40
 *         Author:  mien, m@p58.net
 * =====================================================================================
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <netdb.h>
#include <signal.h>

#include "net.h"
#include "http/server.h"
#include "config.h"
#include "factory.h"
#include "dispatcher.h"

#define DEFAULT_CONFIG_FILE "conf/simq.conf"

static void daemonize() {
    int fd;

    if (fork() != 0) exit(0);
    setsid();

    if ((fd = open("/dev/null", O_RDWR, 0)) != -1) {
        dup2(fd, STDIN_FILENO);
        dup2(fd, STDOUT_FILENO);
        dup2(fd, STDERR_FILENO);
        if (fd > STDERR_FILENO) close(fd);
    }
}

static void sigShutdownHandler(int sig) {
    char *msg;
    switch (sig) {
    case SIGINT:
        msg = "Received SIGINT scheduling shutdown...\n";
        break;
    case SIGTERM:
        msg = "Received SIGTERM scheduling shutdown...\n";
        break;
    default:
        msg = "Received shutdown signal, scheduling shutdown...\n";
    };
    printf(msg);
}

void setupSignalHandlers(void) {
    struct sigaction act;

    sigemptyset(&act.sa_mask);
    act.sa_flags = 0;
    act.sa_handler = sigShutdownHandler;
    sigaction(SIGTERM, &act, NULL);
    sigaction(SIGINT, &act, NULL);
}

int main(int argc, char* argv[])
{
    /* 加载配置 */
    loadConfig(argv[0],
        argc == 2 ? argv[1] : DEFAULT_CONFIG_FILE);

    /* 设定用户和组 */
    setUidGid();

    /* 信号处理 */
    signal(SIGHUP, SIG_IGN);
    signal(SIGPIPE, SIG_IGN);
    setupSignalHandlers();

    /* 守护进程 */
    if (!strcmp(getConfig("server_daemonize"), "yes"))
        daemonize();

    /* 初始 */
    initServer();
    initDispatcher();

    factoryCreate();
    factoryRestore();

    /* 开启服务 */
    tcpListen(
        getConfig("server_host"),
        getConfig("server_port"),
        httpServeIn,
        httpServeOut);

    /* 释放 */
    factoryDump();
    factoryFree();

    freeServer();
    freeDispatcher();
    freeConfig();
    
    /* 返回成功 */
    return EXIT_SUCCESS;
}
